package com.nanhai.buddhist.college.module.collegebase.service.accommodationroom;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nanhai.buddhist.college.framework.common.pojo.PageResult;
import com.nanhai.buddhist.college.framework.common.util.number.NumberUtils;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.accommodationroom.vo.AccommodationRoomCreateReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.accommodationroom.vo.AccommodationRoomExportReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.accommodationroom.vo.AccommodationRoomPageReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.accommodationroom.vo.AccommodationRoomUpdateReqVO;
import com.nanhai.buddhist.college.module.collegebase.convert.accommodationroom.AccommodationRoomConvert;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.accommodationbed.AccommodationBedDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.accommodationbuilding.AccommodationBuildingDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.accommodationfloor.AccommodationFloorDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.accommodationreside.AccommodationResideDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.accommodationroom.AccommodationRoomDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.colleges.CollegesDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.departments.DepartmentsDO;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.accommodationbed.AccommodationBedMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.accommodationreside.AccommodationResideMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.accommodationroom.AccommodationRoomMapper;
import com.nanhai.buddhist.college.module.collegebase.enums.BedTypeEnum;
import com.nanhai.buddhist.college.module.collegebase.service.accommodationbed.AccommodationBedService;
import com.nanhai.buddhist.college.module.collegebase.service.accommodationbuilding.AccommodationBuildingService;
import com.nanhai.buddhist.college.module.collegebase.service.accommodationfloor.AccommodationFloorService;
import com.nanhai.buddhist.college.module.collegebase.service.colleges.CollegesService;
import com.nanhai.buddhist.college.module.collegebase.service.departments.DepartmentsService;
import jodd.util.StringUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.nanhai.buddhist.college.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants.ACCOMMODATION_ROOM_BED_EXISTS;
import static com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants.ACCOMMODATION_ROOM_NOT_EXISTS;

/**
 * 房间 Service 实现类
 *
 * @author AKai
 */
@Service
@Validated
public class AccommodationRoomServiceImpl implements AccommodationRoomService {

    @Resource
    private AccommodationRoomMapper accommodationRoomMapper;

    @Resource
    private AccommodationBedMapper accommodationBedMapper;

    @Resource
    private CollegesService collegesService;

    @Resource
    private DepartmentsService departmentsService;

    @Resource
    private AccommodationFloorService accommodationFloorService;

    @Resource
    private AccommodationBuildingService accommodationBuildingService;


    @Resource
    private AccommodationBedService accommodationBedService;

    @Resource
    private AccommodationResideMapper accommodationResideMapper;


    @Override
    @Transactional
    public String createAccommodationRoom(AccommodationRoomCreateReqVO createReqVO) {
        // 插入
        AccommodationRoomDO accommodationRoom = AccommodationRoomConvert.INSTANCE.convert(createReqVO);

        accommodationRoom.setSerialNumber(NumberUtils.getCodeByServ("FJ"));
        accommodationRoomMapper.insert(accommodationRoom);

        addBedDO(createReqVO.getLowerBedList(), createReqVO.getUpBedList(), accommodationRoom.getId());
        // 返回
        return accommodationRoom.getId();
    }

    // 批量新增床铺
    private void addBedDO(List<String> lowerBedLis, List<String> upBedLis, String accommodationRoomId) {
        // 批量新增下铺
        lowerBedLis.forEach(item -> {
            AccommodationBedDO accommodationBedDO = new AccommodationBedDO();
            accommodationBedDO.setRoomId(accommodationRoomId);
            accommodationBedDO.setBedType(BedTypeEnum.LOWER.getType());
            accommodationBedDO.setBedName(item);
            accommodationBedMapper.insert(accommodationBedDO);
        });

        // 批量新增上铺
        upBedLis.forEach(item -> {
            AccommodationBedDO accommodationBedDO = new AccommodationBedDO();
            accommodationBedDO.setRoomId(accommodationRoomId);
            accommodationBedDO.setBedType(BedTypeEnum.UP.getType());
            accommodationBedDO.setBedName(item);
            accommodationBedMapper.insert(accommodationBedDO);
        });
    }


    @Override
    @Transactional
    public void updateAccommodationRoom(AccommodationRoomUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateAccommodationRoomExists(updateReqVO.getId());
        // 更新
        AccommodationRoomDO updateObj = AccommodationRoomConvert.INSTANCE.convert(updateReqVO);
        accommodationRoomMapper.updateById(updateObj);


        deletedDedDO(updateReqVO.getId());
        addBedDO(updateReqVO.getLowerBedList(), updateReqVO.getUpBedList(), updateReqVO.getId());

    }

    @Override
    @Transactional
    public void deleteAccommodationRoom(String id) {
        // 校验存在
        this.validateAccommodationRoomExists(id);

        //TODO 有人入住了， 不能删除房间
        // 判断是否有床位存在

        List<AccommodationBedDO> accommodationBedListByRoomId = accommodationBedService.getAccommodationBedListByRoomId(id);
        if (CollectionUtils.isNotEmpty(accommodationBedListByRoomId)) {
            List<String> collect = accommodationBedListByRoomId.stream().map(AccommodationBedDO::getId).collect(Collectors.toList());
            List<AccommodationResideDO> accommodationResideDOS = accommodationResideMapper.selectList(new LambdaQueryWrapper<AccommodationResideDO>().in(AccommodationResideDO::getBedId, collect));
            if (CollectionUtils.isNotEmpty(accommodationResideDOS)) {
                throw exception(ACCOMMODATION_ROOM_BED_EXISTS);
            }
        }
        // 删除
        accommodationRoomMapper.deleteById(id);
        deletedDedDO(id);
    }

    private void deletedDedDO(String id) {
        if (StringUtil.isBlank(id)) {
            return;
        }
        List<AccommodationBedDO> bedDOS = accommodationBedMapper.selectList(new LambdaQueryWrapper<AccommodationBedDO>().eq(AccommodationBedDO::getRoomId, id));
        if (CollectionUtil.isEmpty(bedDOS)) {
            return;
        }
        List<String> bedIds = bedDOS.stream().map(AccommodationBedDO::getId).collect(Collectors.toList());
        accommodationResideMapper.delete(new LambdaQueryWrapper<AccommodationResideDO>().in(AccommodationResideDO::getBedId, bedIds));
        accommodationBedMapper.delete(new LambdaQueryWrapper<AccommodationBedDO>().eq(AccommodationBedDO::getRoomId, id));
    }

    private void validateAccommodationRoomExists(String id) {
        if (accommodationRoomMapper.selectById(id) == null) {
            throw exception(ACCOMMODATION_ROOM_NOT_EXISTS);
        }
    }

    @Override
    public AccommodationRoomDO getAccommodationRoom(String id) {
        AccommodationRoomDO accommodationRoomDO = accommodationRoomMapper.selectById(id);
        if (ObjectUtil.isNull(accommodationRoomDO)) {
            return accommodationRoomDO;
        }

        AccommodationFloorDO accommodationFloor = accommodationFloorService.getAccommodationFloor(accommodationRoomDO.getFloorId());
        if (ObjectUtil.isNull(accommodationFloor)) {
            return accommodationRoomDO;
        }

        accommodationRoomDO.setBuildingId(Optional.of(accommodationFloor).map(AccommodationFloorDO::getBuildingId).orElse(""));
        return accommodationRoomDO;
    }

    @Override
    public List<AccommodationRoomDO> getAccommodationRoomList(Collection<String> ids) {
        return com.nanhai.buddhist.college.framework.common.util.collection.CollectionUtils.isEmpty(ids) ? Collections.emptyList() : accommodationRoomMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<AccommodationRoomDO> getAccommodationRoomPage(AccommodationRoomPageReqVO pageReqVO) {
        PageResult<AccommodationRoomDO> page = accommodationRoomMapper.selectPage(pageReqVO);
        page.setList(this.setPageResVo(page.getList()));
        return page;
    }

    @Override
    public List<AccommodationRoomDO> getAccommodationRoomList(AccommodationRoomExportReqVO exportReqVO) {
        List<AccommodationRoomDO> list = accommodationRoomMapper.selectList(exportReqVO);
        return setPageResVo(list);
    }


    /**
     * 封装 学院 系部 楼层 昵称 楼等
     *
     * @param list
     * @return
     */
    @Override
    public List<AccommodationRoomDO> setPageResVo(List<AccommodationRoomDO> list) {
        if (CollectionUtil.isEmpty(list)) {
            return list;
        }
        List<String> collegeIds = list.stream().map(AccommodationRoomDO::getCollegeId).collect(Collectors.toList());
        List<CollegesDO> collegesList = collegesService.getCollegesList(collegeIds);

        List<String> departmentIds = list.stream().map(AccommodationRoomDO::getDepartmentId).collect(Collectors.toList());
        List<DepartmentsDO> departmentsList = departmentsService.getDepartmentsList(departmentIds);

        List<String> floorIds = list.stream().map(AccommodationRoomDO::getFloorId).collect(Collectors.toList());
        List<AccommodationFloorDO> accommodationFloorList = accommodationFloorService.getAccommodationFloorList(floorIds);

        List<String> buildingIds = accommodationFloorList.stream().map(AccommodationFloorDO::getBuildingId).distinct().collect(Collectors.toList());

        List<AccommodationBuildingDO> buildingList = accommodationBuildingService.getAccommodationBuildingList(buildingIds);

        list.forEach(item -> {
            // 根设置学院昵称
            if (CollectionUtil.isNotEmpty(collegesList)) {
                List<CollegesDO> collegesDOS = collegesList.stream().filter(s -> s.getId().equals(item.getCollegeId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collegesDOS)) {
                    CollegesDO collegesDO = (collegesDOS).get(0);
                    item.setCollegeName(Optional.ofNullable(collegesDO).map(CollegesDO::getCollegeName).orElse(""));
                }

            }
            // 设置系部昵称
            if (CollectionUtil.isNotEmpty(departmentsList)) {
                final List<DepartmentsDO> departments = departmentsList.stream().filter(s -> s.getId().equals(item.getDepartmentId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(departments)) {
                    DepartmentsDO departmentsDO = departments.get(0);
                    item.setDepartmentName(Optional.ofNullable(departmentsDO).map(DepartmentsDO::getDepartmentName).orElse(""));
                }
            }

            if (CollectionUtil.isNotEmpty(accommodationFloorList)) {
                List<AccommodationFloorDO> floorDOS = accommodationFloorList.stream().filter(s -> s.getId().equals(item.getFloorId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(floorDOS)) {
                    // 设置楼层昵称
                    AccommodationFloorDO floorDO = floorDOS.get(0);
                    item.setFloorName(Optional.ofNullable(floorDO).map(AccommodationFloorDO::getFloorName).orElse(""));

                    // 根据楼层 设置楼栋昵称
                    if (CollectionUtil.isNotEmpty(buildingList)) {
                        List<AccommodationBuildingDO> buildingDOS = buildingList.stream().filter(s -> s.getId().equals(floorDO.getBuildingId())).collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(buildingDOS)) {
                            AccommodationBuildingDO buildingDO = buildingDOS.get(0);
                            item.setBuildingName(buildingDO.getBuildingName());
                        }

                    }

                }
            }


        });
        return list;
    }

    @Override
    public List<AccommodationRoomDO> getAccommodationRoomListByDepartmentId(String departmentId) {
        return accommodationRoomMapper.selectList(AccommodationRoomDO::getDepartmentId, departmentId);
    }

    @Override
    public List<AccommodationRoomDO> getAccommodationRoomListByFloorId(String floorId) {
        return accommodationRoomMapper.selectList(AccommodationRoomDO::getFloorId, floorId);
    }

}
